
#include <stdint.h>
#include <stdlib.h>
#include <Utility.h>
#include "tag_type.h"
#include "simple_protocol.h"
#include "Debug.h"
#include <Log.h>
#include <Reader/Reader.h>

static int mfp_active(void){
	phacDiscLoop_Sw_DataParams_t * pDataParams = reader.pDiscLoop;
	uint8_t      PH_MEMLOC_REM bCidEnabled;
    uint8_t      PH_MEMLOC_REM bCid;
    uint8_t      PH_MEMLOC_REM bNadSupported;
    uint8_t      PH_MEMLOC_REM bFwi;
    uint8_t      PH_MEMLOC_REM bFsdi;
    uint8_t      PH_MEMLOC_REM bFsci;
	phStatus_t status;
	PH_CHECK_SUCCESS_FCT(status, phhalHw_SetConfig(pDataParams->pHalDataParams, PHHAL_HW_CONFIG_SET_EMD, PH_ON));

	PH_CHECK_SUCCESS_FCT(status, phpalI14443p4a_ActivateCard(
		pDataParams->pPal1443p4aDataParams,
		pDataParams->sTypeATargetInfo.sTypeA_I3P4.bFsdi,
		pDataParams->sTypeATargetInfo.sTypeA_I3P4.bCid,
		pDataParams->sTypeATargetInfo.sTypeA_I3P4.bDri,
		pDataParams->sTypeATargetInfo.sTypeA_I3P4.bDsi,
		pDataParams->sTypeATargetInfo.sTypeA_I3P4.pAts));

	/* Retrieve 14443-4A protocol parameter */
	PH_CHECK_SUCCESS_FCT(status, phpalI14443p4a_GetProtocolParams(
		pDataParams->pPal1443p4aDataParams,
		&bCidEnabled,
		&bCid,
		&bNadSupported,
		&bFwi,
		&bFsdi,
		&bFsci));


	/* Set 14443-4 protocol parameter */
	PH_CHECK_SUCCESS_FCT(status, phpalI14443p4_SetProtocol(
		pDataParams->pPal14443p4DataParams,
		bCidEnabled,
		bCid,
		bNadSupported,
		pDataParams->sTypeATargetInfo.sTypeA_I3P4.bNad,
		bFwi,
		bFsdi,
		bFsci));

	return status;
}


static int mfp_write_perso(uint16_t block_addr, uint8_t num_block, uint8_t* block_data){
	void * pDataParams = phNfcLib_GetDataParams(PH_COMP_AL_MFPEVX);
	return phalMfpEVx_WritePerso(pDataParams, 1, block_addr, num_block, block_data);
}

static int mfp_commit_perso(uint8_t option){
	void * pDataParams = phNfcLib_GetDataParams(PH_COMP_AL_MFPEVX);
	return  phalMfpEVx_CommitPerso(
        pDataParams,                                                 /**< [In] Pointer to this layer's parameter structure. */
        option,                                                    /**< [In] Option to be used for Security Level switching.
                                                                             *          \arg #PHAL_MFPEVX_MAINTIAN_BACKWARD_COMPATIBILITY
                                                                             *          \arg #PHAL_MFPEVX_SWITCH_SECURITY_LEVEL_1
                                                                             *          \arg #PHAL_MFPEVX_SWITCH_SECURITY_LEVEL_3
                                                                             */
        PHAL_MFPEVX_ISO14443_L4                                                 /**< [In] ISO14443 protocol to be used.
                                                                             *          \arg #PHAL_MFPEVX_ISO14443_L3
                                                                             *          \arg #PHAL_MFPEVX_ISO14443_L4
                                                                             */
    );
}

static int mfp_auth(uint8_t sl, uint16_t key_addr, uint8_t* keys){
	uint8_t ver = 0;
	uint8_t keyNo = 1;
	void* key_store = phNfcLib_GetDataParams(PH_COMP_KEYSTORE);
	phKeyStore_FormatKeyEntry(key_store, 1, PH_KEYSTORE_KEY_TYPE_AES128);
	phKeyStore_SetKeyAtPos(key_store, keyNo, 0,	PH_KEYSTORE_KEY_TYPE_AES128, keys, ver);
	void * pDataParams = phNfcLib_GetDataParams(PH_COMP_AL_MFPEVX);
	uint8_t bLenPcdCap2 = 6;
	uint8_t PcdCap2In[6] = {0};
	uint8_t PdCap2[6];
	uint8_t PcdCap2Out[6];
	phStatus_t status;
	if(sl == 1){
		status = phalMfpEVx_AuthenticateSL1(pDataParams, 0, 1, key_addr, keyNo,
	    		ver, 0, NULL, bLenPcdCap2, PcdCap2In, PcdCap2Out, PdCap2);
	}
	else{
		// phStatus_t phalMfpEVx_AuthenticateSL3(void * pDataParams, uint8_t bFirstAuth, uint16_t wBlockNr, uint16_t wKeyNumber, uint16_t wKeyVersion,
    	// uint8_t bLenDivInput, uint8_t * pDivInput, uint8_t bLenPcdCap2, uint8_t * pPcdCap2In, uint8_t * pPcdCap2Out, uint8_t * pPdCap2)

		status = phalMfpEVx_AuthenticateSL3(pDataParams, 1, key_addr, keyNo,
	    		ver, 0, NULL, bLenPcdCap2, PcdCap2In, PcdCap2Out, PdCap2);
	}
	return status;
}

static int mfp_read_block(uint16_t block_addr, uint8_t* data){
	void * pDataParams = phNfcLib_GetDataParams(PH_COMP_AL_MFPEVX);
	phStatus_t status = phalMfpEVx_Read(
	       	pDataParams,                                                 /**< [In] Pointer to this layer's parameter structure. */
	        PHAL_MFPEVX_ENCRYPTION_ON,                                                 /**< [In] Type of communication to be used. Based on this flag the command code
	                                                                             *        will be updated.
	                                                                             *          \arg #PHAL_MFPEVX_ENCRYPTION_OFF
	                                                                             *          \arg #PHAL_MFPEVX_ENCRYPTION_ON
	                                                                             */
	        PHAL_MFPEVX_MAC_ON_RESPONSE_ON,                                                 /**< [In] Indicate whether the response should be maced. Based on this flag the
	                                                                             *        command code will be updated.
	                                                                             *          \arg #PHAL_MFPEVX_MAC_ON_RESPONSE_OFF
	                                                                             *          \arg #PHAL_MFPEVX_MAC_ON_RESPONSE_ON
	                                                                             */
	        PHAL_MFPEVX_MAC_ON_COMMAND_ON,                                                  /**< [In] Indicate whether the command should be maced. Based on this flag the
	                                                                             *        command code will be updated.
	                                                                             *          \arg #PHAL_MFPEVX_MAC_ON_COMMAND_OFF
	                                                                             *          \arg #PHAL_MFPEVX_MAC_ON_COMMAND_ON
	                                                                             */
	        block_addr,                                                  /**< [In] PICC block number from which the data should be read. */
	        1,                                                 /**< [In] Number of blocks to be read.\n
	                                                                             *          \c 15 block for Native communication if configured as Software component. \n
	                                                                             *          \c 13 blocks if configured as Sam X or Sam NonX component.
	                                                                             */
	        data                                                   /**< [Out] The data to be read. This buffer should have data equal to ((NumBlocks * 16) + 8),
	                                                                             *         where 16 is one block size and 8 bytes is for storing the MAC received form PICC.
	                                                                             *         The last 8 bytes will be cleared once returned to the application.
	                                                                             */
	    );
	return status;
}

static int mfp_write_block(uint16_t block_addr, uint8_t* data){
	uint8_t TMC[4];
	uint8_t TMV[8];

	void * pDataParams = phNfcLib_GetDataParams(PH_COMP_AL_MFPEVX);
	phStatus_t status = phalMfpEVx_Write(
			pDataParams, 												/**< [In] Pointer to this layer's parameter structure. */
			PHAL_MFPEVX_ENCRYPTION_ON, 												/**< [In] Type of communication to be used. Based on this flag the command code
																				 *		  will be updated.
																				 *			\arg #PHAL_MFPEVX_ENCRYPTION_OFF
																				 *			\arg #PHAL_MFPEVX_ENCRYPTION_ON
																				 */
			PHAL_MFPEVX_MAC_ON_RESPONSE_ON,												/**< [In] Indicate whether the response should be maced. Based on this flag the
																				 *		  command code will be updated.
																				 *			\arg #PHAL_MFPEVX_MAC_ON_RESPONSE_OFF
																				 *			\arg #PHAL_MFPEVX_MAC_ON_RESPONSE_ON
																				 */
			block_addr,													/**< [In] PICC block number to which the data should be written. */
			1, 												/**< [In] Number of blocks to write.\n
																				 *			\c 15 block for Native communication if configured as Software component. \n
																				 *			\c 13 blocks if configured as Sam X or Sam NonX component.
																				 */
			data,													/**< [In] The data to be written. This buffer should have data equal to NumBlocks * 16,
																				 *		  where 16 is one block size.
																				 */
			TMC, 													/**< [Out] Only available is the block is a TMProtected block. The buffer will have 4
																				 *		   bytes of Transaction MAC counter information.
																				 */
			TMV														/**< [Out] Only available is the block is a TMProtected block. The buffer will have 8
																				 *		   bytes of Transaction MAC value.
																				 */
		);
	return status;
}

static int mfp_read_value_block(uint16_t block_addr, uint8_t* data){
	uint8_t AddrData;
	void * pDataParams = phNfcLib_GetDataParams(PH_COMP_AL_MFPEVX);
	phStatus_t status = phalMfpEVx_ReadValue(
			pDataParams, 												/**< [In] Pointer to this layer's parameter structure. */
			PHAL_MFPEVX_ENCRYPTION_ON, 												/**< [In] Type of communication to be used. Based on this flag the command code
																				 *		  will be updated.
																				 *			\arg #PHAL_MFPEVX_ENCRYPTION_OFF
																				 *			\arg #PHAL_MFPEVX_ENCRYPTION_ON
																				 */
			PHAL_MFPEVX_MAC_ON_RESPONSE_ON, 												/**< [In] Indicate whether the response should be maced. Based on this flag the
																				 *		  command code will be updated.
																				 *			\arg #PHAL_MFPEVX_MAC_ON_RESPONSE_OFF
																				 *			\arg #PHAL_MFPEVX_MAC_ON_RESPONSE_ON
																				 */
			PHAL_MFPEVX_MAC_ON_COMMAND_ON,													/**< [In] Indicate whether the command should be maced. Based on this flag the
																				 *		  command code will be updated.
																				 *			\arg #PHAL_MFPEVX_MAC_ON_COMMAND_OFF
																				 *			\arg #PHAL_MFPEVX_MAC_ON_COMMAND_ON
																				 */
			block_addr,													/**< [In] PICC block number from which the value should be read. */
			data,													/**< The value read from the specified block number. The buffer will have 4 bytes
																				 *	  of value information.
																				 */
			&AddrData 												/**< [Out] The address from the read value information. */
		);
	return status;
}

static int mfp_write_value_block(uint16_t block_addr, uint8_t* data){
	uint8_t TMC[4];
	uint8_t TMV[8];
	void * pDataParams = phNfcLib_GetDataParams(PH_COMP_AL_MFPEVX);
	phStatus_t status = phalMfpEVx_WriteValue(
			pDataParams,                                                 /**< [In] Pointer to this layer's parameter structure. */
			1,                                                 /**< [In] Type of communication to be used. Based on this flag the command code
																				*        will be updated.
																				*          \arg #PHAL_MFPEVX_ENCRYPTION_OFF
																				*          \arg #PHAL_MFPEVX_ENCRYPTION_ON
																				*/
			1,                                                /**< [In] Indicate whether the response should be maced. Based on this flag the
																				*        command code will be updated.
																				*          \arg #PHAL_MFPEVX_MAC_ON_RESPONSE_OFF
																				*          \arg #PHAL_MFPEVX_MAC_ON_RESPONSE_ON
																				*/
			block_addr,                                                  /**< [In] PICC block number to which the value should be written. */
			data,                                                   /**< [In] The value to be written. This buffer should have value equal to 4 bytes. */
			(uint8_t) block_addr,                                                  /**< [In] The address to be written. */
			TMC,                                                     /**< [Out] Only available is the block is a TMProtected block. The buffer will have 4
																				*         bytes of Transaction MAC counter information.
																				*/
			TMV                                                      /**< [Out] Only available is the block is a TMProtected block. The buffer will have 8
																				*         bytes of Transaction MAC value.
																				*/
		);
	return status;
}

static int mfp_increment_value_block(uint16_t block_addr, uint8_t* data){
	uint8_t TMC[4];
	uint8_t TMV[8];
	void * pDataParams = phNfcLib_GetDataParams(PH_COMP_AL_MFPEVX);
	phStatus_t status = phalMfpEVx_IncrementTransfer(
        pDataParams,                                                 /**< [In] Pointer to this layer's parameter structure. */
        PHAL_MFPEVX_MAC_ON_RESPONSE_ON,                                    /**< [In] Indicate whether the response should be maced. Based on this flag the
                                                                             *        command code will be updated.
                                                                             *          \arg #PHAL_MFPEVX_MAC_ON_RESPONSE_OFF
                                                                             *          \arg #PHAL_MFPEVX_MAC_ON_RESPONSE_ON
                                                                             */
        block_addr,                                            /**< [In] PICC block number to be used for incrementing the value. */
        block_addr,                                       /**< [In] PICC block number to be used for transferring the value. */
        data,                                                   /**< [In] The value to be incremented and transferred. This buffer should have 4 bytes
                                                                             *        value information. The value to be incremented and transferred should be LSB first order. \n
                                                                             *        \c For Ex. If the value to be incremented is by 1 times then the pValue buffer will be, \n
                                                                             *           0x01, 0x00, 0x00, 0x00.
                                                                             */
        TMC,                                                     /**< [Out] Only available is the block is a TMProtected block. The buffer will have 4
                                                                             *         bytes of Transaction MAC counter information.
                                                                             */
        TMV                                                      /**< [Out] Only available is the block is a TMProtected block. The buffer will have 8
                                                                             *         bytes of Transaction MAC value.
                                                                             */
    );
	return status;
}

static int mfp_decrement_value_block(uint16_t block_addr, uint8_t* data){
	uint8_t TMC[4];
	uint8_t TMV[8];
	void * pDataParams = phNfcLib_GetDataParams(PH_COMP_AL_MFPEVX);
	phStatus_t status = phalMfpEVx_DecrementTransfer(
        pDataParams,                                                 /**< [In] Pointer to this layer's parameter structure. */
        PHAL_MFPEVX_MAC_ON_RESPONSE_ON,                                    /**< [In] Indicate whether the response should be maced. Based on this flag the
                                                                             *        command code will be updated.
                                                                             *          \arg #PHAL_MFPEVX_MAC_ON_RESPONSE_OFF
                                                                             *          \arg #PHAL_MFPEVX_MAC_ON_RESPONSE_ON
                                                                             */
        block_addr,                                            /**< [In] PICC block number to be used for decrementing the value. */
        block_addr,                                       /**< [In] PICC block number to be used for transferring the value. */
        data,                                                   /**< [In] The value to be decremented and transferred. This buffer should have 4 bytes
                                                                             *        value information. The value to be decremented and transferred should be LSB first order. \n
                                                                             *        \c For Ex. If the value to be decremented is by 1 times then the pValue buffer will be, \n
                                                                             *           0x01, 0x00, 0x00, 0x00.
                                                                             */
        TMC,                                                     /**< [Out] Only available is the block is a TMProtected block. The buffer will have 4
                                                                             *         bytes of Transaction MAC counter information.
                                                                             */
        TMV                                                      /**< [Out] Only available is the block is a TMProtected block. The buffer will have 8
                                                                             *         bytes of Transaction MAC value.
                                                                             */
    );
	
	return status;
}

static int mfp_copy_value_block(uint16_t src_addr, uint16_t dest_addr){
	void * pDataParams = phNfcLib_GetDataParams(PH_COMP_AL_MFPEVX);
	phStatus_t status = phalMfpEVx_Restore(
        pDataParams,                                                 /**< [In] Pointer to this layer's parameter structure. */
        PHAL_MFPEVX_MAC_ON_RESPONSE_ON,                                              /**< [In] Indicate whether the response should be maced. Based on this flag the
                                                                             *        command code will be updated.
                                                                             *          \arg #PHAL_MFPEVX_MAC_ON_RESPONSE_OFF
                                                                             *          \arg #PHAL_MFPEVX_MAC_ON_RESPONSE_ON
                                                                             */
        src_addr                                                   /**< [In] PICC block number to be used for restoring the value. */
    );
	if(status){
		return status;
	}
	uint8_t TMC[4];
	uint8_t TMV[8];
	status = phalMfpEVx_Transfer(
        pDataParams,                                                 /**< [In] Pointer to this layer's parameter structure. */
        PHAL_MFPEVX_MAC_ON_RESPONSE_ON,                                             /**< [In] Indicate whether the response should be maced. Based on this flag the
                                                                             *        command code will be updated.
                                                                             *          \arg #PHAL_MFPEVX_MAC_ON_RESPONSE_OFF
                                                                             *          \arg #PHAL_MFPEVX_MAC_ON_RESPONSE_ON
                                                                             */
        dest_addr,                                                  /**< [In] PICC block number to be used for transferring the value. */
        TMC,                                                     /**< [Out] Only available is the block is a TMProtected block. The buffer will have 4
                                                                             *         bytes of Transaction MAC counter information.
                                                                             */
        TMV                                                      /**< [Out] Only available is the block is a TMProtected block. The buffer will have 8
                                                                             *         bytes of Transaction MAC value.
                                                                             */
    );
	 
	return status;
}



/*--------------------------------------------------------------------------------------------------*/
/*
1.5.22.1. MFP_WritePerso
Command: [1B00][UInt16: BlockNr][Byte Array(16): Data]
Response: [00][Bool: Result]
Example
Command: 1B00004000000000000000000000000000000000
(BlockNr: 0040, Data: 00000000000000000000000000000000)
Response: 0001
(Result: true)
*/

static int api_mfp_write_perso(buffer_t* command, buffer_t* response){
#pragma pack(1)
	typedef struct{
		uint16_t BlockNr;
		uint8_t Data[16];
	}mfp_write_perso_param_t;
#pragma pack()

	int ret;
	mfp_write_perso_param_t* param = (mfp_write_perso_param_t*)command->data;
	ret = mfp_write_perso(param->BlockNr, 1, param->Data);
	API_CHECK(ret);
	return ERR_NONE;
}
/*--------------------------------------------------------------------------------------------------*/
/*
1.5.22.2. MFP_CommitPerso
Command: [1B01]
Response: [00][Bool: Result]
Example
Command: 1B01
Response: 0001
(Result: true)
*/
static int api_mfp_commit_perso(buffer_t* command, buffer_t* response){
	int ret;
	ret = mfp_commit_perso(PHAL_MFPEVX_SWITCH_SECURITY_LEVEL_1);
	API_CHECK(ret);
	return ERR_NONE;
}
/*--------------------------------------------------------------------------------------------------*/
/*
1.5.22.2. MFP_CommitPerso
Command: [1B0A]
Response: [00][Bool: Result]
Example
Command: 1B0A
Response: 0001
(Result: true)
*/
static int api_mfp_commit_perso3(buffer_t* command, buffer_t* response){
	int ret;
	ret = mfp_commit_perso(PHAL_MFPEVX_SWITCH_SECURITY_LEVEL_3);
	API_CHECK(ret);
	return ERR_NONE;
}
/*--------------------------------------------------------------------------------------------------*/
/*
1.5.22.3. MFP_Authenticate
Command: [1B02][Byte: CryptoEnv][UInt16: KeyBNr][Byte Array(16): Key]
Response: [00][Bool: Result]
Example
Command: 1B0200004000000000000000000000000000000000
(CryptoEnv: 00, KeyBNr: 0040, Key: 00000000000000000000000000000000)
Response: 0001
(Result: true)
*/
/*
指令需要根据卡处于SL1或者SL3使用对应的协议层。
SL1使用ISO14443-3，SL3使用ISO14443-4
*/
static int api_mfp_auth(buffer_t* command, buffer_t* response){
#pragma pack(1)
	typedef struct{
		uint8_t CryptoEnv;
		uint16_t KeyBNr;
		uint8_t Key[16];
	}mfp_auth_param_t;
#pragma pack()

	int ret;
	mfp_auth_param_t* param = (mfp_auth_param_t*)command->data;
	uint8_t sl = 3;
	if(reader.dwActivatedType != E_PH_NFCLIB_TYPEA_LAYER4){
		ret = mfp_active();
		API_CHECK(ret);
		reader.dwActivatedType = E_PH_NFCLIB_TYPEA_LAYER4;
	}
	ret = mfp_auth(sl, param->KeyBNr, param->Key);
	API_CHECK(ret);
	return ERR_NONE;
}
/*--------------------------------------------------------------------------------------------------*/
/*
1.5.22.4. MFP_ReadBlock
Command: [1B03][Byte: CryptoEnv][UInt16: Block]
Response: [00][Bool: Result][Byte Array(16): Data]
Example
Command: 1B03000400
(CryptoEnv: 00, Block: 0400)
Response: 000101020304050607080900010203040506
(Result: true, Data: 01020304050607080900010203040506)
*/
static int api_mfp_read_block(buffer_t* command, buffer_t* response){
#pragma pack(1)
	typedef struct{
		uint8_t CryptoEnv;
		uint16_t Block;
	}mfp_read_block_param_t;
#pragma pack()

	mfp_read_block_param_t* param = (mfp_read_block_param_t*)command->data;
	uint8_t* rdata = net_buf_simple_tail(response);
	int ret = mfp_read_block(param->Block, rdata);
	API_CHECK(ret);
	TRACE_D("env:%d, blcok: %04X, data: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
		param->CryptoEnv, param->Block, 
		rdata[0], rdata[1], rdata[2], rdata[3], 
		rdata[4], rdata[5], rdata[6], rdata[7], 
		rdata[8], rdata[9], rdata[10], rdata[11], 
		rdata[12], rdata[13], rdata[14], rdata[15]);
	net_buf_simple_add(response, 16);
	return ERR_NONE;
}

/*--------------------------------------------------------------------------------------------------*/
/*
1.5.22.5. MFP_WriteBlock
Command: [1B04][Byte: CryptoEnv][UInt16: Block][Byte Array(16): Data]
Response: [00][Bool: Result]
Example
Command: 1B0400040001020304050607080900010203040506
(CryptoEnv: 00, Block: 0400, Data: 01020304050607080900010203040506)
Response: 0001
(Result: true)
*/
static int api_mfp_write_block(buffer_t* command, buffer_t* response){
#pragma pack(1)
	typedef struct{
		uint8_t CryptoEnv;
		uint16_t Block;
		uint8_t Data[16];
	}mfp_write_block_param_t;
#pragma pack()

	mfp_write_block_param_t* param = (mfp_write_block_param_t*)command->data;
	TRACE_D("env:%d, blcok: %04X, data: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
		param->CryptoEnv, param->Block, 
		param->Data[0], param->Data[1], param->Data[2], param->Data[3], 
		param->Data[4], param->Data[5], param->Data[6], param->Data[7], 
		param->Data[8], param->Data[9], param->Data[10], param->Data[11], 
		param->Data[12], param->Data[13], param->Data[14], param->Data[15]);
	int ret = mfp_write_block(param->Block, param->Data);
	API_CHECK(ret);
	return ERR_NONE;
}
/*--------------------------------------------------------------------------------------------------*/
/*
1.5.22.6. MFP_ReadValueBlock
Command: [1B05][Byte: CryptoEnv][UInt16: Block]
Response: [00][Bool: Result][UInt32: Value]
Example
Command: 1B05000400
(CryptoEnv: 00, Block: 0400)
Response: 000100000000
(Result: true, Value: 0)
*/
static int api_mfp_read_value_block(buffer_t* command, buffer_t* response){
#pragma pack(1)
	typedef struct{
		uint8_t CryptoEnv;
		uint16_t Block;
	}mfp_read_value_block_param_t;
#pragma pack()

	mfp_read_value_block_param_t* param = (mfp_read_value_block_param_t*)command->data;
	uint8_t* rdata = net_buf_simple_tail(response);
	int ret = mfp_read_value_block(param->Block, rdata);
	API_CHECK(ret);
	net_buf_simple_add(response, sizeof(uint32_t));
	return ERR_NONE;
}
/*--------------------------------------------------------------------------------------------------*/
/*
1.5.22.7. MFP_WriteValueBlock
Command: [1B06][Byte: CryptoEnv][UInt16: Block][UInt32: Value]
Response: [00][Bool: Result]
Example
Command: 1B0600040000000000
(CryptoEnv: 00, Block: 0400, Value: 00000000)
Response: 0001
(Result: true)
*/
static int api_mfp_write_value_block(buffer_t* command, buffer_t* response){
#pragma pack(1)
	typedef struct{
		uint8_t CryptoEnv;
		uint16_t Block;
		uint32_t Value;
	}mfp_write_value_block_param_t;
#pragma pack()

	mfp_write_value_block_param_t* param = (mfp_write_value_block_param_t*)command->data;	
	int ret = mfp_write_value_block(param->Block, (uint8_t*)&param->Value);
	API_CHECK(ret);
	return ERR_NONE;
}
/*--------------------------------------------------------------------------------------------------*/
/*
1.5.22.8. MFP_IncrementValueBlock
Command: [1B07][Byte: CryptoEnv][UInt16: Block][UInt32: Value]
Response: [00][Bool: Result]
Example
Command: 1B0700040001000000
(CryptoEnv: 00, Block: 0400, Value: 01000000)
Response: 0001
(Result: true)
*/
static int api_mfp_increment_value_block(buffer_t* command, buffer_t* response){
#pragma pack(1)
	typedef struct{
		uint8_t CryptoEnv;
		uint16_t Block;
		uint32_t Value;
	}mfp_increment_value_block_param_t;
#pragma pack()

	mfp_increment_value_block_param_t* param = (mfp_increment_value_block_param_t*)command->data;	
	int ret = mfp_increment_value_block(param->Block, (uint8_t*)&param->Value);
	API_CHECK(ret);
	return ERR_NONE;
}
/*--------------------------------------------------------------------------------------------------*/
/*
1.5.22.9. MFP_DecrementValueBlock
Command: [1B08][Byte: CryptoEnv][UInt16: Block][UInt32: Value]
Response: [00][Bool: Result]
Example
Command: 1B0800040001000000
(CryptoEnv: 00, Block: 0400, Value: 01000000)
Response: 0001
(Result: true)
*/
static int api_mfp_decrement_value_block(buffer_t* command, buffer_t* response){
#pragma pack(1)
	typedef struct{
		uint8_t CryptoEnv;
		uint16_t Block;
		uint32_t Value;
	}mfp_decrement_value_block_param_t;
#pragma pack()

	mfp_decrement_value_block_param_t* param = (mfp_decrement_value_block_param_t*)command->data;	
	int ret = mfp_decrement_value_block(param->Block, (uint8_t*)&param->Value);
	API_CHECK(ret);
	return ERR_NONE;
}
/*--------------------------------------------------------------------------------------------------*/
/*
1.5.22.10. MFP_CopyValueBlock
Command: [1B09][Byte: CryptoEnv][UInt16: SourceBlock][UInt16: DestBlock]
Response: [00][Bool: Result]
Example
Command: 1B090004000500
(CryptoEnv: 00, SourceBlock: 0400, DestBlock: 0500)
Response: 0001
(Result: true)
*/
static int api_mfp_copy_value_block(buffer_t* command, buffer_t* response){
#pragma pack(1)
	typedef struct{
		uint8_t CryptoEnv;
		uint16_t SourceBlock;
		uint16_t DestBlock;
	}mfp_copy_value_block_param_t;
#pragma pack()
	
	mfp_copy_value_block_param_t* param = (mfp_copy_value_block_param_t*)command->data;	
	int ret = mfp_copy_value_block(param->SourceBlock, param->DestBlock);
	API_CHECK(ret);
	return ERR_NONE;
}
/*--------------------------------------------------------------------------------------------------*/

// static const api_func_t api_mifare_plus_func[] = {
// 	{.func = 0x00, api_mfp_write_perso},
// 	{.func = 0x01, api_mfp_commit_perso},
// 	{.func = 0x02, api_mfp_auth},
// 	{.func = 0x03, api_mfp_read_block},
// 	{.func = 0x04, api_mfp_write_block},
// 	{.func = 0x05, api_mfp_read_value_block},
// 	{.func = 0x06, api_mfp_write_value_block},
// 	{.func = 0x07, api_mfp_increment_value_block},
// 	{.func = 0x08, api_mfp_decrement_value_block},
// 	{.func = 0x09, api_mfp_copy_value_block},
// };

static const api_entry_t api_mifare_plus_entries[] = {
	[0] = api_mfp_write_perso,
	[1] = api_mfp_commit_perso,
	[2] = api_mfp_auth,
	[3] = api_mfp_read_block,
	[4] = api_mfp_write_block,
	[5] = api_mfp_read_value_block,
	[6] = api_mfp_write_value_block,
	[7] = api_mfp_increment_value_block,
	[8] = api_mfp_decrement_value_block,
	[9] = api_mfp_copy_value_block,
	[10] = api_mfp_commit_perso3,
};

// static int mifare_plus_call_api(buffer_t* command, buffer_t* response){
// 	uint8_t fun = net_buf_simple_pull_u8(command);
// 	const uint8_t fun_num = sizeof(api_mifare_plus_func)/sizeof(api_mifare_plus_func[0]);
// 	return protocol_call_fun(fun, api_mifare_plus_func, fun_num, command, response);
// }
static int mifare_plus_call_api(buffer_t* command, buffer_t* response){
	uint8_t fun = net_buf_simple_pull_u8(command);
	const uint8_t fun_num = sizeof(api_mifare_plus_entries)/sizeof(api_mifare_plus_entries[0]);
	if(fun < fun_num){
		return api_mifare_plus_entries[fun](command, response);
	}
	return ERR_INVALID_FUNCTION;
}

static int mifare_plus_api(buffer_t* command, buffer_t* response){
	int ret = mifare_plus_call_api(command, response);
	if(ret > 0){
		return ret;
	}
	protocol_response_result(response, ret);
	return ERR_NONE;
}

SIMPLE_API_DEFINE(API_CLASS_MIFARE_PLUS, mifare_plus_api);


